package cn.iocoder.yudao.module.erp.service.stock.goods;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.module.erp.controller.admin.stock.goods.vo.GoodsImportExcelVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.goods.vo.GoodsImportRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.goods.vo.GoodsPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.goods.vo.GoodsSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.business.group.goodscategory.GoodsCategoryDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.business.warehouse.WarehouseDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.goods.GoodsDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.goodswarehouselink.GoodsWarehouseLinkDO;
import cn.iocoder.yudao.module.erp.dal.mysql.business.group.goodscategory.GoodsCategoryMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.business.warehouse.WarehouseMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.goods.GoodsMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.goodswarehouselink.GoodsWarehouseLinkMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;

/**
 * 物品 Service 实现类
 *
 * @author maxuxu
 */
@Service
@Validated
public class GoodsServiceImpl implements GoodsService {

    @Resource
    private GoodsMapper goodsMapper;
    @Resource
    private WarehouseMapper warehouseMapper;

    @Resource
    private GoodsWarehouseLinkMapper goodsWarehouseLinkMapper;

    @Resource
    private GoodsCategoryMapper goodsCategoryMapper;

    @Override
    public Long createGoods(GoodsSaveReqVO createReqVO) {
        // 插入
        GoodsDO goods = BeanUtils.toBean(createReqVO, GoodsDO.class);
        goodsMapper.insert(goods);
        // 新增仓库库存
        goodsWarehouseLinkMapper.insert(new GoodsWarehouseLinkDO()
                .setGoodsId(goods.getId()).setInventory(BigDecimal.ZERO).setWarehouseId(createReqVO.getWarehouseId()));
        // 返回
        return goods.getId();
    }

    @Override
    public void updateGoods(GoodsSaveReqVO updateReqVO) {
        // 校验存在
        validateGoodsExists(updateReqVO.getId());
        // 更新
        GoodsDO updateObj = BeanUtils.toBean(updateReqVO, GoodsDO.class);
        goodsMapper.updateById(updateObj);
    }

    @Override
    public void deleteGoods(Long id) {
        // 校验存在
        validateGoodsExists(id);
        // 删除
        goodsMapper.deleteById(id);
    }

    private void validateGoodsExists(Long id) {
        if (goodsMapper.selectById(id) == null) {
            throw exception(GOODS_NOT_EXISTS);
        }
    }

    @Override
    public GoodsDO getGoods(Long id) {
        return goodsMapper.selectById(id);
    }

    @Override
    public PageResult<GoodsDO> getGoodsPage(GoodsPageReqVO pageReqVO) {
        return goodsMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务，异常则回滚所有导入
    public GoodsImportRespVO importGoodsList(List<GoodsImportExcelVO> list, Boolean updateSupport, Long loginUserId) {
        if (CollUtil.isEmpty(list)) {
            throw exception(GOODS_IMPORT_EXCEL_DATA_EMPTY);
        }
        GoodsImportRespVO respVO = GoodsImportRespVO.builder().failureGoodsNames(new LinkedHashMap<>()).createGoodsNames(new ArrayList<>())
                .updateGoodsNames(new ArrayList<>()).build();
        list.forEach(goods ->{
            // 校验，判断是否有不符合的原因 todo: 后面会添加更多的校验，目前是校验仓库是否存在
            try {
                validateGoodsForCreateOrUpdate(null,null, goods.getWarehouse());
            } catch (ServiceException ex) {
                respVO.getFailureGoodsNames().put(goods.getName(), ex.getMessage());
                return;
            }
            GoodsDO selectByCode = goodsMapper.selectByCode(goods.getCode());
            // 校验物品编码唯一，没有才能insert，否则看是否更新
            if (selectByCode == null){
                GoodsDO goodsDO = BeanUtils.toBean(goods, GoodsDO.class);
                // 处理类目 todo: 多级类目处理，不存在先新增类目，再把对应类目信息添加到goods表

                //用于插入类目
                GoodsCategoryDO goodsCategoryDO = new GoodsCategoryDO();
                //判断一级目录是否为空
                if(StrUtil.isNotEmpty(goods.getCategoryOne())){
                    GoodsCategoryDO goodsCategoryDOOne = goodsCategoryMapper.selectByParentAndName(null, goods.getCategoryOne());
                    if(BeanUtil.isNotEmpty(goodsCategoryDOOne)){
                        //判断二级目录是否为空
                        if(StrUtil.isNotEmpty(goods.getCategoryTwo())){
                            GoodsCategoryDO goodsCategoryDOTwo = goodsCategoryMapper.selectByParentAndName(null, goods.getCategoryTwo());
                            // 判断二级目录是否存在
                            if(BeanUtil.isNotEmpty(goodsCategoryDOTwo)){
                                // 判断三级目录是否为空
                                if(StrUtil.isNotEmpty(goods.getCategoryThree())){
                                    GoodsCategoryDO goodsCategoryDOThree = goodsCategoryMapper.selectByParentAndName(null,goods.getCategoryThree());
                                    if(BeanUtil.isNotEmpty(goodsCategoryDOThree)){
                                        goodsDO.setCategoryName(goodsCategoryDOThree.getName()).setCategoryId(goodsCategoryDOThree.getId());
                                    }else{//三级目录不存在
                                        goodsCategoryDO.setName(goods.getCategoryThree()).setParentId(goodsCategoryDOTwo.getId());
                                        goodsCategoryMapper.insert(goodsCategoryDO);
                                        goodsDO.setCategoryName(goodsCategoryDO.getName()).setCategoryId(goodsCategoryDO.getId());
                                    }
                                }else{ //三级目录为空
                                    goodsDO.setCategoryName(goodsCategoryDOTwo.getName()).setCategoryId(goodsCategoryDOTwo.getId());
                                }
                            }else{ //二级目录不存在
                                goodsCategoryDO.setName(goods.getCategoryTwo()).setParentId(goodsCategoryDOOne.getId());
                                goodsCategoryMapper.insert(goodsCategoryDO);
                                goodsDO.setCategoryName(goodsCategoryDO.getName()).setCategoryId(goodsCategoryDO.getId());
                            }
                        }else{ //二级目录为空
                            goodsDO.setCategoryName(goodsCategoryDOOne.getName()).setCategoryId(goodsCategoryDOOne.getId());
                        }
                    }else{ //一级目录不存在
                        goodsCategoryDO.setName(goods.getCategoryOne()).setParentId(0L);
                        goodsCategoryMapper.insert(goodsCategoryDO);
                        goodsDO.setCategoryName(goodsCategoryDO.getName()).setCategoryId(goodsCategoryDO.getId());

                    }
                }else{
                    goodsDO.setCategoryName("默认");
                }

                // 插入物品信息
                goodsMapper.insert(goodsDO);

                // 获取仓库并插入到连接表
                WarehouseDO warehouseDO = warehouseMapper.selectByName(goods.getWarehouse());
                goodsWarehouseLinkMapper.insert(new GoodsWarehouseLinkDO().setGoodsId(goodsDO.getId()).setWarehouseId(warehouseDO.getId()));
                respVO.getCreateGoodsNames().add(goods.getName());
                return;
            }
            if (!updateSupport) {
                respVO.getFailureGoodsNames().put(goods.getName(), GOODS_GOODSCODE_EXISTS.getMsg());
                return;
            }
            GoodsDO updateGoods = BeanUtils.toBean(goods, GoodsDO.class);
            updateGoods.setId(selectByCode.getId());
            goodsMapper.updateById(updateGoods);
            respVO.getUpdateGoodsNames().add(goods.getName());
        });
        return respVO;
    }

    @Override
    public void deleteAnyGoods(List<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        goodsMapper.deleteBatchIds(ids);
    }

    @Override
    public void validProductList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            throw exception(GOODS_LIST_EMPTY);
        }
        List<GoodsDO> goodsDOS = goodsMapper.selectBatchIds(ids);
        goodsDOS.forEach(goodsDO -> {
            if (goodsDO == null || goodsDO.getId() == null) {
                throw exception(GOODS_NOT_EXISTS);
            }
        });
    }

    private void validateGoodsForCreateOrUpdate(Long id, String goodsName,String warehouseName) {
        // 关闭数据权限，避免因为没有数据权限，查询不到数据，进而导致唯一校验不正确
        DataPermissionUtils.executeIgnore(() -> {
            // 校验客户存在
//            validateCustomerExists(id);
            // 校验客户名称名唯一
//            validateCustomerUnique(id, username);
            // 校验仓库是否存在
            validateWarehouseExists(warehouseName);
        });
    }
    private void validateWarehouseExists(String name) {
        if (warehouseMapper.selectByName(name) == null) {
            throw exception(WAREHOUSE_NOT_EXISTS);
        }
    }

}